<template>
  <div style="height:100%; width: 100%; overflow: auto;">
    <div class="buttonList">
      <el-button
        type="primary"
        :key="index"
        v-for="(button, index) in buttonList"
        style="position: absolute; transition: .3s;"
        :style="buttonStyle[index]"
        @click="runScript(button.pipe)"
      >{{ button.name }}</el-button>
      <el-button
        :type="fold ? 'primary' : 'danger'"
        :icon="fold ? 'el-icon-menu' : 'el-icon-close'"
        circle
        @click="menu"
        class="menu"
        :style="{ transform: fold ? 'scale(1.2)' : 'scale(0.8)' }"
      ></el-button>
    </div>
    <codemirror v-model="serviceConfig" :options="options" style="font-size: 16px; height: 100%; width: 100%;" class="edit" ref="edit" @blur="blur"></codemirror>
  </div>
</template>

<script lang="ts">
import "../css/vscode.css";
import "codemirror/lib/codemirror.css";
import "codemirror/mode/javascript/javascript.js";

import { Component, Vue, Watch } from "vue-property-decorator";
import { Config } from "../typing";
import { codemirror } from "vue-codemirror";
import { getConfig, getServiceConfig, setServiceConfig, serviceConfigEmitter, socket } from "../init";

import "codemirror/mode/javascript/javascript";
import "codemirror/mode/nginx/nginx";

@Component
export default class ServiceConfig extends Vue {
  public serviceConfig: string = "";
  public config: Config;
  public $refs: any;
  public $route: any;
  public options: any = {
    indentUnit: 4,
    tabSize: 4,
    mode: "",
    theme: "vscode",
    lineNumbers: true,
    line: true,
    smartIndent: true,
    electricChars: true,
  };

  public buttonStyle: { right: string; transform: string; }[] = [];
  public fold = true;
  public buttonList = [];

  constructor(...args: any) {
    super(...args);
    serviceConfigEmitter.on("update", this.onUpdate);
  }

  public onUpdate(serviceName: string, serviceConfig: string) {
    if (serviceName === this.$route.params.serviceName) {
      this.serviceConfig = serviceConfig;
    }
  }

  public async mounted() {
    if (this.$refs.edit.$el.childNodes[1]) {
      this.$refs.edit.$el.childNodes[1].style.height = "100%"
    }
    this.onChang(this.$route.params.serviceName);
  }

  @Watch("$route.params.serviceName")
  public async onChang(serviceName: string) {
    const mode = this.$route.params.mode || "javascript";
    if (mode === "json") {
      this.options.mode = { name: 'javascript', json: true };
    } else {
      this.options.mode = `text/${ mode }`;
    }
    this.fold = true;
    this.serviceConfig = await getServiceConfig(this.$route.params.serviceName);
    this.config = await getConfig();
    this.buttonList = this.config.service[this.$route.params.serviceName].buttonList || [];
    this.buttonStyle = [];
    for (let i = 0; i < this.buttonList.length; i ++) {
      this.buttonStyle.push({
        right: "-25px",
        transform: "scale(0)"
      });
    }
  }

  public blur() {
    setServiceConfig(this.$route.params.serviceName, this.serviceConfig);
  }

  public beforeDestroy() {
    serviceConfigEmitter.removeListener("update", this.onUpdate);
  }

  public runScript(pipe: string) {
    socket.send({
      pipe,
      type: "runServiceScript",
      serviceName: this.$route.params.serviceName,
    });
  }

  public menu() {
    this.fold = !this.fold;
    if (this.fold) {
      for (const style of this.buttonStyle) {
        style.right = "-25px";
        style.transform = "scale(0)";
      }
    } else {
      for (let i = 0; i < this.buttonStyle.length; i ++) {
        const style = this.buttonStyle[i];
        style.right = 50 + i * 120 + "px";
        style.transform = "scale(1)";
      }
    }
  }
}
</script>

<style scoped>
.buttonList {
  position: fixed;
  z-index: 5;
  right: 40px;
  bottom: 40px;
}

.menu {
  position: relative;
  z-index: 6;
  opacity: 0.5;
  transition: .3s;
}

.menu:hover {
  opacity: 1;
}
</style>